package cnki.tpi.base;


import cnki.tpi.kbatis.annotation.Column;
import cnki.tpi.util.ConstantUtil;
import cnki.tpi.util.StrUtil;
import com.kbase.jdbc.ConnectionImpl;
import com.kbase.jdbc.PreparedStatement;
import com.kbase.jdbc.ResultSetImpl;
import com.kbase.jdbc.StatementImpl;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.ResultSet;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import kbase.KBaseClient;
import kbase.struct.TPI_DIRINFO;
import kbase.struct.TPI_DISKINFO;
import kbase.struct.TPI_RETURN_RESULT;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class DataContext<T> implements IDataContext {

    @Autowired
    private DataSourceManager kbaseDs;
    private static final Logger logger = LoggerFactory.getLogger(DataContext.class);

    @Value("${max.exportExcelNum}")
    private Integer exportExcelNum;

    public <T> List<T> excuteQuery(String sql, Class<T> t) {
        List<T> result = null;
        ResultSet rs = null;
        Connection conn = null;
        StatementImpl pst = null;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            rs = pst.executeQuery(sql);
            result = handle(rs, parserFieldList(sql), t);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {
            try {
                if (rs != null && !rs.isClosed()) {
                    rs.close();
                }
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return result;
    }

    /**
     * 关键词标红,主要用于前台检索
     *
     * @param sql
     * @param t
     * @return
     */
    public <T> List<T> excuteQueryRed(String sql, Class<T> t) {
        List<T> result = null;
        ResultSet rs = null;
        ResultSetImpl rsi = null;
        Connection conn = null;
        StatementImpl pst = null;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            rsi = (ResultSetImpl) pst.executeQuery(sql);
            rsi.SetHitWordMarkFlag("$$$", "###");
            result = handle(rsi, parserFieldList(sql), t);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {
            try {
                if (rsi != null && !rsi.isClosed()) {
                    rsi.close();
                }
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return result;
    }

    private <T> List<T> handle(ResultSet rs, String[] fieldList, Class<T> type) {
        List<T> list = new ArrayList<T>();
        try {
            int count = fieldList.length;
            int countNum = 0;
            while (rs.next()) {
               countNum ++ ;
                if (countNum <= exportExcelNum) {
                    T t = null;
                    for (int i = 0; i < count; i++) {
                        String name = fieldList[i].trim();// 该方法获取列名.获取一系列字段名称.例如name,age...
                        String value = rs.getString(i + 1);// 获取字段值
                        Field field = type.getDeclaredField(name);// 获取field对象
                        if (StrUtil.checkStringNull(value)) {
                            if (t == null) {
                                t = type.newInstance();
                            }
                        }
                        if (field != null && t != null) {
                            field.setAccessible(true);
                            if (field.getType() == String.class) {
                                field.set(t, value);// 设置值
                            } else if (field.getType() == int.class) {
                                field.set(t, Integer.parseInt(value));// 设置值
                            } else if (field.getType() == Integer.class) {
                                if("".equals(value) || value == null){
                                    field.set(t, Integer.parseInt("0"));// 设置值
                                }else{
                                    field.set(t, Integer.parseInt(value));// 设置值
                                }
                            }
                            else {
                                field.set(t, value);// 设置值
                            }
                        }
                    }
                    if (t != null) {
                        list.add(t);
                    }
                }else{
                    break;
                }
            }
        }catch(Exception e){
                e.printStackTrace();
                logger.error(e.getMessage());
            }



        return list;
    }

    private String[] parserFieldList(String sql) {
        String[] result = {};
        try {
            sql = sql.toLowerCase();
            String field = sql.substring(7, sql.indexOf("from") - 1);
            result = field.split(",");
            for (int i = 0; i < result.length; i++) {
                String str = result[i];
                if (str.contains(" as ")) {
                    int x = str.indexOf(" as ");
                    result[i] = str.substring(x + 4, str.length()).trim();
                } else {
                    result[i] = str.trim();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        }
        return result;
    }

    @Override
    public List<Map<String, String>> excuteQueryList(String sql) {
        List<Map<String, String>> result = new ArrayList<Map<String, String>>();
        ResultSet rs = null;
        Connection conn = null;
        StatementImpl pst = null;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            rs = pst.executeQuery(sql);
            String[] fieldList = parserFieldList(sql);
            int count = fieldList.length;
            while (rs.next()) {
                Map<String, String> map = new HashMap<String, String>();
                for (int i = 0; i < count; i++) {
                    String name = fieldList[i].trim();// 该方法获取列名.获取一系列字段名称.例如name,age...
                    String value = rs.getString(i + 1);// 获取字段值
                    map.put(name, value);

                }
                result.add(map);
            }
        } catch (Exception e) {
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {
            try {
                if (rs != null && !rs.isClosed()) {
                    rs.close();
                }
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> excuteQueryListObj(String sql) {
        List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
        ResultSet rs = null;
        Connection conn = null;
        StatementImpl pst = null;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            rs = pst.executeQuery(sql);

            String[] fieldList = parserFieldList(sql);
            int count = fieldList.length;
            while (rs.next()) {
                Map<String, Object> map = new HashMap<String, Object>();
                for (int i = 0; i < count; i++) {
                    String name = fieldList[i].trim();// 该方法获取列名.获取一系列字段名称.例如name,age...
                    String value = rs.getString(i + 1);// 获取字段值
                    map.put(name, value);

                }
                result.add(map);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {
            try {
                if (rs != null && !rs.isClosed()) {
                    rs.close();
                }
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return result;
    }

    @Override
    public int excuteQueryRecordNumber(String sql) {
        int result = 0;
        ResultSet rs = null;
        Connection conn = null;
        StatementImpl pst = null;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            rs = pst.executeQuery(sql);
            while (rs.next()) {
                if (rs.getString(1) != null) {
                    result = Integer.parseInt(rs.getString(1));
                }
                break;
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {
            try {
                if (rs != null && !rs.isClosed()) {
                    rs.close();
                }
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return result;
    }

    /**
     * 根据查询条件，返回一个对象集合
     * sql语句需要将具体字段显示出来
     *
     * @param sql
     * @param list 查询条件值集合
     * @param t
     * @return
     */
    @Override
    public <T> List<T> excuteQuery(String sql, List list, Class<T> t) {
        List<T> result = null;
        PreparedStatement ptmt = null;
        Connection conn = null;
        ResultSetImpl rsi = null;
        try {
            // 从连接池中取得 连接
            conn = kbaseDs.getConnection();
            // 准备执行语句
            ptmt = (PreparedStatement) conn.prepareStatement(sql);
            // 解析参数列表
            if (list != null && list.size() > 0) {
                for (int i = 0; i < list.size(); i++) {
                    String str = list.get(i).toString();
                    ptmt.setString(i + 1, str);
                }
            }
            rsi = (ResultSetImpl) ptmt.executeQuery(sql);
            rsi.SetHitWordMarkFlag("$$$", "###");
            result = handle(rsi, parserFieldList(sql), t);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {

            try {
                if (rsi != null && !rsi.isClosed()) {
                    rsi.close();
                }
                if (ptmt != null && !ptmt.isClosed()) {
                    ptmt.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }

        }
        return result;
    }

    @Override
    public Boolean excuteDelete(String sql) {
        Connection conn = null;
        StatementImpl pst = null;
        boolean flag = true;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            flag = pst.execute(sql);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {
            try {
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return flag;
    }

    public Boolean excuteCreateDataBaseOrTable(String sql) {
        Connection conn = null;
        StatementImpl pst = null;
        boolean flag = true;
        try {
            conn = this.kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            flag = pst.execute(sql);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {
            try {
                if (pst != null && !pst.isClosed())
                    pst.close();
                if (conn != null && !conn.isClosed())
                    conn.close();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return Boolean.valueOf(flag);
    }

    @Override
    public Boolean excuteInsertList(List<String> sqlList) {
        Connection conn = null;
        StatementImpl pst = null;
        boolean flag = true;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            for (String sql : sqlList) {
                flag = pst.execute(sql);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            try {
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return flag;
    }

    public int excuteSql(String sql) {
        Connection conn = null;
        StatementImpl pst = null;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            return pst.executeUpdate(sql);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {
            try {
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return -1;
    }

    @Override
    public Boolean excuteUpdate(String sql) {
        Connection conn = null;
        StatementImpl pst = null;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            pst.executeUpdate(sql);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {
            try {
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return false;
    }

    @Override
    public Boolean excuteUpdateList(List<String> sqlList) {
        Connection conn = null;
        StatementImpl pst = null;
        boolean flag = true;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            for (String sql : sqlList) {
                flag = pst.execute(sql);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            try {
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return flag;
    }

    /**
     * 新增记录并返回sysid
     */
    public int updateAndReturnSysid(String sql) {
        Connection conn = null;
        StatementImpl pst = null;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            return pst.executeUpdate(sql);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {
            try {
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return 0;
    }

    /**
     * 仅返回一个对象
     *
     * @param sql
     * @param t
     * @return
     */
    public <T> T excuteQueryReturnOne(String sql, Class<T> t) {
        List<T> result = null;
        ResultSet rs = null;
        Connection conn = null;
        StatementImpl pst = null;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            rs = pst.executeQuery(sql);
            result = handle(rs, parserFieldList(sql), t);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {
            try {
                if (rs != null && !rs.isClosed()) {
                    rs.close();
                }
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        if (result.size() > 0) {
            return result.get(0);
        }
        return null;
    }

    @Override
    public List<Map<String, String>> excuteQueryList_light(String sql) {
        List<Map<String, String>> result = new ArrayList<Map<String, String>>();
        PreparedStatement ptmt = null;
        Connection conn = null;
        ResultSetImpl rsi = null;
        try {
            // 从连接池中取得 连接
            conn = kbaseDs.getConnection();
            // 准备执行语句
            ptmt = (PreparedStatement) conn.prepareStatement(sql);

            rsi = (ResultSetImpl) ptmt.executeQuery(sql);
            rsi.SetHitWordMarkFlag("###font>", "###/font>");
            String[] fieldList = parserFieldList(sql);
            int count = fieldList.length;
            while (rsi.next()) {
                Map<String, String> map = new HashMap<String, String>();
                for (int i = 0; i < count; i++) {
                    String name = fieldList[i].trim();// 该方法获取列名.获取一系列字段名称.例如name,age...
                    String value = "";
                    if (rsi.getString(i + 1) != null) {
                        value = rsi.getString(i + 1).replaceAll("<", "&lt;").replaceAll("###", "<");// 获取字段值
                    }
                    map.put(name, value);

                }
                result.add(map);
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {

            try {
                if (rsi != null && !rsi.isClosed()) {
                    rsi.close();
                }
                if (ptmt != null && !ptmt.isClosed()) {
                    ptmt.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }

        }
        return result;
    }

    @Override
    public List<Map<String, String>> getMultiCountByDb(List<Map<String, String>> dbList, List<String> arr,
                                                       String sql) {
        ResultSetImpl rsi = null;
        Connection conn = null;
        StatementImpl pst = null;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            rsi = (ResultSetImpl) pst.executeQuery(sql);
            KBaseClient kBaseClient = ((ConnectionImpl) conn).getKbaseClient();
            for (String dbcode : arr) {
                String searchtype = (String) excuteQueryListObj("SELECT SEARCHTYPE FROM SYS_CMS_DATABASE where DATABASECODE='" + dbcode + "'").get(0).get("searchtype");
                int i = kBaseClient.KBase_GetVQRecordCountByName(rsi.getResultSetImplhset(), dbcode + (searchtype.equals(ConstantUtil.SEARCH_TYPE_0) ? ConstantUtil.DB_METADATA_SUFFIX : ""));
                for (Map<String, String> map : dbList) {
                    if (dbcode.equals(map.get("databasecode"))) {
                        map.put("sumcount", String.valueOf(i));
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {
            try {
                if (rsi != null && !rsi.isClosed()) {
                    rsi.close();
                }
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return null;
    }

    @Override
    public Integer getMaxId(String fieldName, String tableName) {
        String sql = "select max(" + fieldName + ") from " + tableName;
        return excuteQueryFristFeildBySql(sql);
    }

    private Integer excuteQueryFristFeildBySql(String sql) {
        Connection conn = null;
        StatementImpl pst = null;
        Integer num = 0;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            ResultSet resultSet = pst.executeQuery(sql);
            while (resultSet.next()) {
                num = resultSet.getInt(1);
            }
            return num;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {
            try {
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return 0;
    }

    @Override
    public Integer getTableCountByCondition(String tableName, String condition) {
        String sql = "select count(*) from " + tableName + condition;
        return excuteQueryFristFeildBySql(sql);
    }

    /**
     * 由于kbase支持的sql语句长度有限，直接使用insert或者update语句会自动截断导致语法出错，从而执行失败
     * 针对比较长的文本数据，先将基本信息插入或者更新，然后进行长文本字段的更新。
     *
     * @param sql         如：SELECT * FROM TPINEWS_METADATA WHERE SYS_FLD_SYSID=16
     * @param columnLabel
     * @param content
     */
    public void updateLongText(String sql, String columnLabel, String content) {
        ResultSetImpl rsi = null;
        Connection conn = null;
        StatementImpl pst = null;
        try {
            conn = kbaseDs.getConnection();
            pst = (StatementImpl) conn.createStatement();
            rsi = (ResultSetImpl) pst.executeQuery(sql);
            rsi.last();
            rsi.updateString(columnLabel, content);
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(sql);
            logger.error(e.getMessage());
        } finally {
            try {
                if (rsi != null && !rsi.isClosed()) {
                    rsi.close();
                }
                if (pst != null && !pst.isClosed()) {
                    pst.close();
                }
                if (conn != null && !conn.isClosed()) {
                    conn.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
    }

    /**
     * 通过实例化对象数据插入表记录
     *
     * @param tableName 待导入记录的表名
     * @param list      实体类对象集合
     * @return
     */
    @Override
    public <T> Boolean insertRecData(String tableName, List<T> list) {
        for (T t : list) {
            insertRecData(tableName, t);
        }
        return true;
    }

    /**
     * 通过实例化对象数据插入表记录
     *
     * @param tableName 待导入记录的表名
     * @param t         实体类对象
     * @return
     */
    @Override
    public <T> Boolean insertRecData(String tableName, T t) {
        String content = parserRecContent(t, null);
        if (content.isEmpty())
            return false;
        return insertRecData(tableName, content);
    }

    /**
     * 通过REC格式数据插入表记录
     *
     * @param tableName 待导入记录的表名
     * @param content   REC格式内容，如： <REC><key1>=value1<key2>=value2
     * @return
     */
    @Override
    public Boolean insertRecData(String tableName, String content) {
        ConnectionImpl conn = null;
        try {
            conn = (ConnectionImpl) this.kbaseDs.getConnection();
            int hCon = conn.getConnectionHset();
            KBaseClient kBaseClient = conn.getKbaseClient();
            String encoding = "GBK";
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String fileName = tableName + "_" + uuid + ".txt";
            String srcFile = System.getProperty("user.dir") + File.separator + fileName;
            File file = new File(srcFile);
            file.delete();
            file.createNewFile();
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), encoding));
            writer.write(content);
            writer.close();
            TPI_RETURN_RESULT nResult = kBaseClient.KBase_GetServerPath(hCon);
            String targetFile = nResult.rtnBuf + File.separator + fileName;
            int nRet = kBaseClient.KBase_WriteFile(hCon, srcFile, targetFile);
            if (nRet < 0) {
                logger.error("上传REC文件失败");
                file.delete();
                return false;
            }
            String sql = "BULKLOAD TABLE %s '%s'";
            Boolean rs = excuteUpdate(String.format(sql, tableName, targetFile));
            if (!rs.booleanValue()) {
                logger.error("导入REC数据失败");
                file.delete();
                return false;
            }
            file.delete();
            nRet = kBaseClient.KBase_DeleteFiles(hCon, targetFile);
            if (nRet < 0)
                logger.error("删除REC文件失败");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            try {
                if (conn != null && !conn.isClosed())
                    conn.close();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return false;
    }

    /**
     * 通过REC文件插入表记录
     *
     * @param tableName 待导入记录的表名
     * @param filePath  REC文件路径
     * @return
     */
    @Override
    public Boolean insertRecFile(String tableName, String filePath) {
        ConnectionImpl conn = null;
        try {
            conn = (ConnectionImpl) this.kbaseDs.getConnection();
            int hCon = conn.getConnectionHset();
            KBaseClient kBaseClient = conn.getKbaseClient();

            File file = new File(filePath);
            TPI_RETURN_RESULT nResult = kBaseClient.KBase_GetServerPath(hCon);
            String targetFile = nResult.rtnBuf + File.separator + file.getName();
            int nRet = kBaseClient.KBase_WriteFile(hCon, filePath, targetFile);
            if (nRet < 0) {
                logger.error("上传REC文件失败");
                return false;
            }
            String sql = "BULKLOAD TABLE %s '%s'";
            Boolean rs = excuteUpdate(String.format(sql, tableName, targetFile));
            if (!rs.booleanValue()) {
                logger.error("导入REC数据失败");
                return false;
            }
            nRet = kBaseClient.KBase_DeleteFiles(hCon, targetFile);
            if (nRet < 0)
                logger.error("删除REC文件失败");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            try {
                if (conn != null && !conn.isClosed())
                    conn.close();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return false;
    }

    /**
     * 通过实例化对象数据更新表记录
     *
     * @param tableName 待更新记录的表名
     * @param list      实体类对象集合
     * @return
     */
    @Override
    public <T> Boolean updateRecData(String columnLabel, String tableName, List<T> list) {
        for (T t : list) {
            updateRecData(columnLabel, tableName, t.getClass());
        }
        return true;
    }

    /**
     * 通过实例化对象数据更新表记录
     *
     * @param columnLabel 更新的主键列，唯一性由用户保证
     * @param tableName   待更新记录的表名
     * @param t           实体类对象
     * @return
     */
    @Override
    public <T> Boolean updateRecData(String columnLabel, String tableName, T t) {
        String content = parserRecContent(t, columnLabel);
        if (content.isEmpty())
            return false;
        return updateRecData(columnLabel, tableName, content);
    }

    /**
     * 通过REC格式数据更新表记录
     *
     * @param columnLabel 更新的主键列，唯一性由用户保证
     * @param tableName   待更新记录的表名
     * @param content     REC格式内容，如： <REC><key1>=value1<key2>=value2
     * @return
     */
    @Override
    public Boolean updateRecData(String columnLabel, String tableName, String content) {
        ConnectionImpl conn = null;
        try {
            String encoding = "GBK";
            String uuid = UUID.randomUUID().toString().replace("-", "");
            String fileName = tableName + "_" + uuid + ".txt";
            String srcFile = System.getProperty("user.dir") + File.separator + fileName;
            File file = new File(srcFile);
            file.delete();
            file.createNewFile();
            BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(file), encoding));
            writer.write(content);
            writer.close();
            conn = (ConnectionImpl) this.kbaseDs.getConnection();
            int hCon = conn.getConnectionHset();
            KBaseClient kBaseClient = conn.getKbaseClient();
            TPI_RETURN_RESULT nResult = kBaseClient.KBase_GetServerPath(hCon);
            String targetFile = nResult.rtnBuf + File.separator + fileName;
            int nRet = kBaseClient.KBase_WriteFile(hCon, srcFile, targetFile);
            if (nRet < 0) {
                logger.error("上传REC文件失败");
                file.delete();
                return false;
            }
            String sql = "DBUM UPDATE TABLE %s FROM '%s' WITH KEY %s";
            Boolean rs = excuteUpdate(String.format(sql, tableName, targetFile, columnLabel));
            if (!rs.booleanValue()) {
                logger.error("更新REC数据失败");
                file.delete();
                return false;
            }
            file.delete();
            nRet = kBaseClient.KBase_DeleteFiles(hCon, targetFile);
            if (nRet < 0)
                logger.error("删除REC文件失败");
            return true;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            try {
                if (conn != null && !conn.isClosed())
                    conn.close();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return false;
    }

    /**
     * 将实例化对象数据转换为REC格式内容
     *
     * @param t           实体类对象，对象属性的值为空时，自动过滤该字段更新
     * @param columnLabel 主键列为空时，表示插入记录，否则更新记录
     * @return
     */
    private <T> String parserRecContent(T t, String columnLabel) {
        String result = "";
        try {
            StringBuilder sbRec = new StringBuilder("<REC>");
            StringBuilder sb = new StringBuilder();
            Class clazz = (Class) t.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field f : fields) {
                f.setAccessible(true);
                //String name = f.getName();
                Column column = f.getAnnotation(Column.class);
                if (column != null) {
                    String name = column.value();
                    String value = "";
                    String type = f.getType().toString();
                    if (type.endsWith("Date")) {
                        DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
                        value = df.format((Date) f.get(t));
                    } else {
                        value = String.valueOf(f.get(t));
                    }
                    if (StrUtil.checkStringNull(value)) {
                        if (StrUtil.checkStringNull(columnLabel) && name.equalsIgnoreCase(columnLabel)) {
                            sbRec.append(String.format("<%s>=%s", name.toUpperCase(), value));
                        } else {
                            sb.append(String.format("<%s>=%s", name.toUpperCase(), value));
                        }
                    }
                }
            }
            result = sbRec.append(sb).toString();
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        }
        return result;
    }

    public boolean KBase_MakeDir(String path) {
        ConnectionImpl conn = null;
        try {
            conn = (ConnectionImpl) this.kbaseDs.getConnection();
            int hCon = conn.getConnectionHset();
            KBaseClient kBaseClient = conn.getKbaseClient();
            int result = kBaseClient.KBase_MakeDir(hCon, path);
            if (result >= 0)
                return true;
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            try {
                if (conn != null && !conn.isClosed())
                    conn.close();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return false;
    }

    public boolean KBase_FileExists(String path) {
        ConnectionImpl conn = null;
        try {
            conn = (ConnectionImpl) this.kbaseDs.getConnection();
            int hCon = conn.getConnectionHset();
            KBaseClient kBaseClient = conn.getKbaseClient();
            int result = kBaseClient.KBase_FileExists(hCon, path);
            if (result == 0)
                return true;
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            try {
                if (conn != null && !conn.isClosed())
                    conn.close();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return false;
    }

    public boolean KBase_RemoveDir(String path) {
        ConnectionImpl conn = null;
        try {
            conn = (ConnectionImpl) this.kbaseDs.getConnection();
            int hCon = conn.getConnectionHset();
            KBaseClient kBaseClient = conn.getKbaseClient();
            int result = kBaseClient.KBase_RemoveDir(hCon, path);
            if (result >= 0)
                return true;
            return false;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            try {
                if (conn != null && !conn.isClosed())
                    conn.close();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return false;
    }

    public TPI_DIRINFO[] KBase_GetServerDirList(String path) {
        ConnectionImpl conn = null;
        TPI_DIRINFO[] tpi_dirinfos = new TPI_DIRINFO[100];
        try {
            conn = (ConnectionImpl) this.kbaseDs.getConnection();
            int hCon = conn.getConnectionHset();
            KBaseClient kBaseClient = conn.getKbaseClient();
            tpi_dirinfos = kBaseClient.KBase_GetServerDirList(hCon, path, 0, 100, 1, tpi_dirinfos);
            return tpi_dirinfos;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            try {
                if (conn != null && !conn.isClosed())
                    conn.close();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return tpi_dirinfos;
    }

    public TPI_DISKINFO[] KBase_GetServerDiskInfo() {
        ConnectionImpl conn = null;
        TPI_DISKINFO[] tpi_diskinfos = new TPI_DISKINFO[26];
        try {
            conn = (ConnectionImpl) this.kbaseDs.getConnection();
            int hCon = conn.getConnectionHset();
            KBaseClient kBaseClient = conn.getKbaseClient();
            tpi_diskinfos = kBaseClient.KBase_GetServerDiskInfo(hCon, 26, tpi_diskinfos);
            return tpi_diskinfos;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            try {
                if (conn != null && !conn.isClosed())
                    conn.close();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return tpi_diskinfos;
    }

    /**
     * 分词
     *
     * @param content 分词内容
     * @return 分词结果
     */
    @Override
    public String wordSegment(String content) {
        String result = "";
        ConnectionImpl conn = null;
        try {
            conn = (ConnectionImpl) this.kbaseDs.getConnection();
            int hCon = conn.getConnectionHset();
            KBaseClient kBaseClient = conn.getKbaseClient();
            TPI_RETURN_RESULT nResult = kBaseClient.KBase_WordSegment(hCon, content);
            result = nResult.rtnBuf;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            try {
                if (conn != null && !conn.isClosed())
                    conn.close();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return result;
    }

    /**
     * 分词
     *
     * @param content          分词内容
     * @param isKeepSingleWord 是否保留单字，若否则去除单字返回词干数组，不管是否都会自动过滤特殊字符
     * @return 分词结果
     */
    @Override
    public List<String> wordSegment(String content, boolean isKeepSingleWord) {
        List<String> result = new ArrayList<String>();
        ConnectionImpl conn = null;
        try {
            conn = (ConnectionImpl) this.kbaseDs.getConnection();
            int hCon = conn.getConnectionHset();
            KBaseClient kBaseClient = conn.getKbaseClient();
            String regEx = "[\n`~!@#$%^&*()+=|{}':;',\\[\\].<>/?~！@#￥%……&*（）——+|{}【】‘；：”“’。， 、？]";
            //content = content.replaceAll(regEx,"");
            TPI_RETURN_RESULT nResult = kBaseClient.KBase_WordSegment(hCon, content);
            String txt = nResult.rtnBuf;
            if (StrUtil.checkStringNull(txt)) {
                String[] tArray = txt.split("/");
                for (int i = 0; i < tArray.length; i++) {
                    String word = tArray[i].replaceAll(regEx, "");
                    if (StrUtil.checkStringNull(word)) {
                        if (!isKeepSingleWord) {
                            if (word.length() > 1) {
                                result.add(tArray[i]);
                            }
                        } else {
                            result.add(tArray[i]);
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            try {
                if (conn != null && !conn.isClosed())
                    conn.close();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return result;
    }

    /**
     * 得到相似词列表
     *
     * @param inputKeyWord 输入的关键词
     * @return 得到结果 [相似词][相似度][词频][|][相似词][相似度][词频]...
     */
    @Override
    public String getRelevantWords(String inputKeyWord) {
        String result = "";
        ConnectionImpl conn = null;
        try {
            conn = (ConnectionImpl) this.kbaseDs.getConnection();
            int hCon = conn.getConnectionHset();
            KBaseClient kBaseClient = conn.getKbaseClient();
            //输入相似词的缓冲大小
            int nReBufLen = 1024;
            //要求最多返回相似词的数量
            int nMax_Relevant_Word_Num = 32;
            //两个词之间的分隔符号
            int nSeperatorChar = '|';
            //是否输出词频信息
            boolean bWordFreqFollowed = true;
            //执行前，必须要有这个表
            //String dbName = "sys_dict_c2e";
            String dbName = "sys_dict_relevant";
            TPI_RETURN_RESULT nResult = kBaseClient.KBase_GetRelevantWords(hCon, inputKeyWord, nReBufLen, nMax_Relevant_Word_Num, nSeperatorChar, bWordFreqFollowed, dbName);
            result = nResult.rtnBuf;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            try {
                if (conn != null && !conn.isClosed())
                    conn.close();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return result;
    }

    /**
     * 得到相似词列表
     *
     * @param inputKeyWord       输入的关键词
     * @param maxRelevantWord    要求最多返回相似词的数量
     * @param seperatorChar      两个词之间的分隔符号
     * @param isWordFreqFollowed 是否输出词频信息
     * @return 得到结果 [相似词][相似度][词频][|][相似词][相似度][词频]...
     */
    @Override
    public String getRelevantWords(String inputKeyWord, int maxRelevantWord, int seperatorChar, boolean isWordFreqFollowed) {
        String result = "";
        ConnectionImpl conn = null;
        try {
            conn = (ConnectionImpl) this.kbaseDs.getConnection();
            int hCon = conn.getConnectionHset();
            KBaseClient kBaseClient = conn.getKbaseClient();
            //输入相似词的缓冲大小
            int nReBufLen = 1024;
            //要求最多返回相似词的数量
            //int nMax_Relevant_Word_Num = 32;
            //两个词之间的分隔符号
            //int nSeperatorChar = '|';
            //是否输出词频信息
            //boolean bWordFreqFollowed = true;
            //执行前，必须要有这个表
            //String dbName = "sys_dict_c2e";
            String dbName = "sys_dict_relevant";
            TPI_RETURN_RESULT nResult = kBaseClient.KBase_GetRelevantWords(hCon, inputKeyWord, nReBufLen, maxRelevantWord, seperatorChar, isWordFreqFollowed, dbName);
            result = nResult.rtnBuf;
        } catch (Exception e) {
            e.printStackTrace();
            logger.error(e.getMessage());
        } finally {
            try {
                if (conn != null && !conn.isClosed())
                    conn.close();
            } catch (Exception e) {
                e.printStackTrace();
                logger.error(e.getMessage());
            }
        }
        return result;
    }

}
